package com.tianfei.crowd.mvc.config;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.tianfei.crowd.constant.CrowdConstants;
import com.tianfei.crowd.exception.AccessForbiddenException;
import com.tianfei.crowd.exception.LoginAcctAlreadyInUserException;
import com.tianfei.crowd.exception.LoginFailedException;
import com.tianfei.crowd.exception.UpdateAcctAlreadyInUserException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import com.google.gson.Gson;
import com.tianfei.crowd.utils.CrowdUtil;
import com.tianfei.crowd.utils.ResultEntity;

import java.io.IOException;

//@ControllerAdvice表示当前类是一个异常处理的类
@ControllerAdvice
public class CrowdExceptionResolver {

    @ExceptionHandler(value = UpdateAcctAlreadyInUserException.class)
    public ModelAndView resolverUpdateAcctAlreadyInUserException(
            //实际捕获的异常
            UpdateAcctAlreadyInUserException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //调用抽取的方法 返回视图
        String viewName = "system-error";
        return commonResolver(viewName, exception, request, response);
    }


    // 新增管理员账户重复时所抛的异常
    @ExceptionHandler(value = LoginAcctAlreadyInUserException.class)
    public ModelAndView resolverLoginAcctAlreadyInUserException(
            //实际捕获的异常
            LoginAcctAlreadyInUserException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //调用抽取的方法 返回视图
        String viewName = "admin/admin-add";
        return commonResolver(viewName, exception, request, response);
    }


    // 未登录访问受保护资源的异常处理
    @ExceptionHandler(value = AccessForbiddenException.class)
    public ModelAndView resolverAccessForbiddenException(
            //实际捕获的异常
            AccessForbiddenException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //调用抽取的方法 返回视图
        String viewName = "admin/admin-login";
        return commonResolver(viewName, exception, request, response);
    }


    // 登录失败异常处理
    @ExceptionHandler(value = Exception.class)
    public ModelAndView resolverLoginFailedException(
            //实际捕获的异常
            Exception exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //调用抽取的方法 返回视图
		String viewName = "system-error";
        return commonResolver(viewName, exception, request, response);
    }


    //@ExceptionHandler让异常类与方法绑定
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolverNullPointException(
            //实际捕获的异常
            NullPointerException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //调用抽取的方法 返回视图
        return commonResolver("system-error", exception, request, response);
    }


    private ModelAndView commonResolver(String viewName, Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //1、判断当前请求是否为Ajax请求
        boolean judgeResultType = CrowdUtil.judgeResultType(request);

        //2、是ajax请求
        if (judgeResultType) {

            //3、获取异常信息
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());

            //4、创建Gson对象
            Gson gson = new Gson();
            //5、将ResultEntity对象转换为Json字符串
            String json = gson.toJson(failed);
            //6、将Json字符串作为响应体返回
            response.getWriter().write(json);
            //7、用了原生的response，就不用返回ModelAndView视图
            return null;
        } else {
            //普通请求
            //8、创建ModelAndView对象
            ModelAndView modelAndView = new ModelAndView();

            //9、添加Exception到视图模型
            modelAndView.addObject(CrowdConstants.ATTR_EXCEPTION_NAME, exception);
            //10、设置视图名
            modelAndView.setViewName(viewName);
            //11、返回视图
            return modelAndView;
        }
    }


}
